interface EventInfo {
    callback: Function;
    target: any;
}

export class EventManager {
    private static instance: EventManager = null;
    private eventMap: Map<string, EventInfo[]> = new Map();

    public static get I(): EventManager {
        if (!this.instance) {
            this.instance = new EventManager();
        }
        return this.instance;
    }

    /**
     * 注册事件
     * @param eName 事件名称
     * @param callback 回调函数
     * @param target 目标对象
     */
    public on(eName: string, callback: Function, target: any): void {
        if (!this.eventMap.has(eName)) {
            this.eventMap.set(eName, []);
        }
        const eventList = this.eventMap.get(eName);
        eventList.push({ callback, target });
    }

    /**
     * 移除事件
     * @param eName 事件名称
     * @param callback 回调函数
     * @param target 目标对象
     */
    public off(eName: string, callback: Function, target: any): void {
        if (!this.eventMap.has(eName)) return;

        const eventList = this.eventMap.get(eName);
        const index = eventList.findIndex(item =>
            item.callback === callback && item.target === target
        );

        if (index !== -1) {
            eventList.splice(index, 1);
        }

        if (eventList.length === 0) {
            this.eventMap.delete(eName);
        }
    }

    /**
     * 触发事件
     * @param eName 事件名称
     * @param args 参数列表
     */
    public emit(eName: string, ...args: any[]): void {
        if (!this.eventMap.has(eName)) return;

        const eventList = this.eventMap.get(eName);
        eventList.forEach(event => {
            event.callback.apply(event.target, args);
        });
    }

    /**
     * 清空所有事件
     */
    public clear(): void {
        this.eventMap.clear();
    }
}
